﻿namespace System
{
    public static class ObjectExtensions
    {
        /// <summary>
        /// Returns a Boolean value indicating whether an expression evaluates to be NULL.
        /// </summary>
        /// <param name="obj">Required. Object expression.</param>
        /// <returns>Returns a Boolean value indicating whether an expression evaluates to be NULL.</returns>
        public static bool IsNull<T>(this T obj)
        {
            return obj == null;
        }

        //public static bool IsDBNull(this object obj)
        //{
        //    return obj == DBNull.Value;
        //}

        /// <summary>
        /// Returns a Boolean value indicating whether a variable is of the indicated Type
        /// </summary>
        /// <param name="obj">Required. Object variable.</param>
        /// <param name="type">The Type to check the object against.</param>
        /// <returns>Returns a Boolean value indicating whether a variable is of the indicated Type</returns>
        public static bool IsType(this object obj, Type type)
        {
            return obj.GetType() == type;
        }

        /// <summary>
        /// Returns a Boolean value indicating whether a variable points to a System.Array.
        /// </summary>
        /// <param name="obj">Required. Object variable.</param>
        /// <returns>Returns a Boolean value indicating whether a variable points to a System.Array.</returns>
        public static bool IsArray(this object obj)
        {
            return obj.GetType().IsArray;
        }

        /// <summary>
        /// Returns a Boolean value indicating whether a variable points to a DateTime object.
        /// </summary>
        /// <param name="obj">Required. Object variable.</param>
        /// <returns>Returns a Boolean value indicating whether a variable points to a DateTime object.</returns>
        public static bool IsDate(this object obj)
        {
            return obj.IsType(typeof(DateTime));
        }

        /// <summary>
        /// Returns a Boolean value indicating whether an expression evaluates to the DBNull class.
        /// Extension Added by dotNetExt.Object
        /// </summary>
        /// <param name="obj">Required. Object expression.</param>
        /// <returns>Returns a Boolean value indicating whether an expression evaluates to the DBNull class.</returns>
        public static bool IsDBNull(this object obj)
        {
            return obj.IsType(typeof(DBNull));
        }

        /// <summary>
        /// Allows you to easily pass an Anonymous type from one function to another
        /// </summary>
        /// <typeparam name="T">The Anonymous Type</typeparam>
        /// <param name="obj">The Anonymous Type</param>
        /// <param name="targetType">The Object to "Cast As" the Anonymous type</param>
        /// <returns></returns>
        public static T CastAs<T>(this Object obj, T targetType)
        {
            return (T)obj;
        }

        public static short GetInt16Value(this object obj)
        {
            return obj.ToInt16();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short GetInt16Value(this object obj, short defaultValue)
        {
            return obj.IsDBNull() ? defaultValue : (short)obj;
        }

        public static short? GetNullableInt16Value(this object obj)
        {
            return obj.ToNullableInt16();
        }

        public static int GetInt32Value(this object obj)
        {
            return obj.ToInt();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int GetInt32Value(this object obj, int defaultValue)
        {
            return obj.IsDBNull() ? defaultValue : obj.ToInt();
        }

        public static int? GetNullableInt32Value(this object obj)
        {
            return obj.ToNullableInt();
        }

        public static long GetInt64Value(this object obj)
        {
            return obj.ToInt64();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long GetInt64Value(this object obj, long defaultValue = 0)
        {
            return obj.IsDBNull() ? defaultValue : (long)obj;
        }

        public static long? GetNullableInt64Value(this object obj)
        {
            return obj.ToNullableInt64();
        }

        public static string GetStringValue(this object obj)
        {
            return obj.GetStringValue(null);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetStringValue(this object obj, string defaultValue)
        {
            return obj.IsDBNull() ? defaultValue : obj.ToString();
        }

        public static string? GetNullableStringValue(this object obj)
        {
            return obj.IsDBNull() ? null : obj.ToString();
        }

        public static DateTime GetDateTimeValue(this object obj)
        {
            return obj.ToDateTime();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime GetDateTimeValue(this object obj, DateTime defaultValue)
        {
            return obj.IsDBNull() ? defaultValue : (DateTime)obj;
        }

        public static DateTime? GetNullableDateTimeValue(this object obj)
        {
            return obj.ToNullableDateTime();
        }

        public static double GetDoubleValue(this object obj)
        {
            return obj.ToDouble();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double GetDoubleValue(this object obj, double defaultValue)
        {
            return obj.IsDBNull() ? defaultValue : (double)obj;
        }

        public static double? GetNullableDouble(this object obj)
        {
            return obj.ToNullableDouble();
        }

        public static decimal GetDecimal(this object obj)
        {
            return obj.ToDecimal();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal GetDecimal(this object obj, decimal defaultValue)
        {
            return obj.IsDBNull() ? defaultValue : (decimal)obj;
        }

        public static decimal? GetNullableDecimal(this object obj)
        {
            return obj.ToNullableDecimal();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static short GetInt16Value(this object[] objs, int index)
        {
            return objs[index].GetInt16Value();
        }

        public static short GetInt16Value(this object[] objs, int index, short defaultValue)
        {
            return objs[index].GetInt16Value(defaultValue);
        }

        public static short? GetNullableInt16Value(this object[] objs, int index)
        {
            return objs[index].GetNullableInt16Value();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static int GetInt32Value(this object[] objs, int index)
        {
            return objs[index].GetInt32Value();
        }

        public static int GetInt32Value(this object[] objs, int index, int defaultValue = 0)
        {
            return objs[index].GetInt32Value(defaultValue);
        }

        public static int? GetNullableInt32Value(this object[] objs, int index)
        {
            return objs[index].GetNullableInt32Value();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long GetInt64Value(this object[] objs, int index)
        {
            return objs[index].GetInt64Value();
        }

        public static long GetInt64Value(this object[] objs, int index, long defaultValue)
        {
            return objs[index].GetInt64Value(defaultValue);
        }

        public static long? GetNullableInt64Value(this object[] objs, int index)
        {
            return objs[index].GetNullableInt64Value();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetStringValue(this object[] objs, int index)
        {
            return objs[index].GetStringValue();
        }

        public static string GetStringValue(this object[] objs, int index, string defaultValue)
        {
            return objs[index].GetStringValue(defaultValue);
        }

        public static string? GetNullableStringValue(this object[] objs, int index)
        {
            return objs[index].GetNullableStringValue();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime? GetDateTimeValue(this object[] objs, int index)
        {
            return objs[index].GetDateTimeValue();
        }

        public static DateTime GetDateTimeValue(this object[] objs, int index, DateTime defaultValue)
        {
            return objs[index].GetDateTimeValue(defaultValue);
        }

        public static DateTime? GetNullableDateTimeValue(this object[] objs, int index)
        {
            return objs[index].GetNullableDateTimeValue();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static double GetDoubleValue(this object[] objs, int index)
        {
            return objs[index].GetDoubleValue();
        }

        public static double GetDoubleValue(this object[] objs, int index, double defaultValue = 0d)
        {
            return objs[index].GetDoubleValue(defaultValue);
        }

        public static double? GetNullableDoubleValue(this object[] objs, int index)
        {
            return objs[index].GetNullableDouble();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <param name="index"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static Decimal GetValueDecimal(this object[] values, int index, Decimal defaultValue = 0m)
        {
            return index >= 0 ? values[index].GetDecimal() : defaultValue;
        }

        /// <summary>
        /// convertir a string
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToString(this object obj)
        {
            if (obj != null && obj != DBNull.Value)
                if (obj.ToString() != "")
                    return obj.ToString();

            return null;
        }

        public static short ToInt16(this object obj)
        {
            return obj.IsNullOrEmpty() ? short.MinValue : (short)obj;
        }

        public static short? ToNullableInt16(this object obj)
        {
            return obj.IsNullOrEmpty() ? null : (short?)obj;
        }

        public static int ToInt(this object obj)
        {
            return obj.IsNullOrEmpty() ? 0 : (int)obj;
        }

        /// <summary>
        /// convertir a integer
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int? ToNullableInt(this object obj)
        {
            return obj.IsNullOrEmpty() ? null : (int?)obj;
        }

        /// <summary>
        /// Convertir a Int64 (long)
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static long ToInt64(this object obj)
        {
            return obj.IsNullOrEmpty() ? 0L : (long)obj;
        }

        public static long? ToNullableInt64(this object obj)
        {
            return obj.IsNullOrEmpty() ? null : (long?)obj;
        }

        public static double ToDouble(this object obj)
        {
            return obj.IsNullOrEmpty() ? 0d : (double)obj;
        }

        /// <summary>
        /// convertir a double
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static double? ToNullableDouble(this object obj)
        {
            return obj.IsNullOrEmpty() ? null : (double?)obj;
        }

        public static decimal ToDecimal(this object obj)
        {
            return obj.IsNullOrEmpty() ? 0m : (decimal)obj;
        }

        /// <summary>
        /// convertir a double
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static decimal? ToNullableDecimal(this object obj)
        {
            return obj.IsNullOrEmpty() ? null : (decimal?)obj;
        }

        public static DateTime ToDateTime(this object obj)
        {
            return obj.IsNullOrEmpty() ? DateTime.MinValue : (DateTime)obj;
        }

        /// <summary>
        /// convertir a datetime
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static DateTime? ToNullableDateTime(this object obj)
        {
            return obj.IsNullOrEmpty() ? null : (DateTime?)obj;
        }

        public static TimeSpan ToTime(this object obj)
        {
            return obj.IsNullOrEmpty() ? TimeSpan.MinValue : Convert.ToDateTime(obj).TimeOfDay;
        }

        /// <summary>
        /// convertir a time
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static TimeSpan? ToNullableTime(this object obj)
        {
            if (obj != null && obj != DBNull.Value)
                if (obj.ToString() != "")
                    return Convert.ToDateTime(obj).TimeOfDay;

            return null;
        }

        public static bool ToBoolean(this object obj)
        {
            return obj.IsNullOrEmpty() ? false : (bool)obj;
        }
        /// <summary>
        /// convertir a boolean
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool? ToNullableBoolean(this object obj)
        {            
            return obj.IsNullOrEmpty() ? null : (bool?)obj;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="compare"></param>
        /// <returns></returns>
        public static bool NotEquals(this object obj, object compare)
        {
            return !obj.Equals(compare);
        }

        public static bool IsNullOrEmpty(this object obj)
        {
            return (obj == null && obj == DBNull.Value) || obj.ToString() == "";
        }
    }
}
